package com.example.bbs.ui.fragment;

import android.annotation.SuppressLint;
import android.os.Bundle;

import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.bbs.R;
import com.example.bbs.ui.tool.RecyclerAdapterLoadMoreWrapper;

import java.util.concurrent.CompletableFuture;

/** enhanced RecyclerView support dynamic loading and refreshing */
public class BrowseFragment extends Fragment {

    public interface BrowseManager<T> {

        int getItemCount();

        T getItem(int pos);

        /** @return 更新的元素个数 */
        int load();

        void reset();
    }

    static final String LOG_TAG = BrowseFragment.class.getSimpleName();
    static final int MIN_REFRESHING_TIME = 1000; // milliseconds
    static final int MIN_LOADING_TIME = 500; // milliseconds

    RecyclerView rvPostList;
    SwipeRefreshLayout srlPostList;
    RecyclerAdapterLoadMoreWrapper mAdapter;
    BrowseManager<?> browseManager;

    public static BrowseFragment newInstance(BrowseManager<?> browseManager,
                                                    RecyclerView.Adapter<RecyclerView.ViewHolder> adapter) {
        BrowseFragment fragment = new BrowseFragment();
        fragment.browseManager = browseManager;
        fragment.mAdapter = new RecyclerAdapterLoadMoreWrapper(adapter);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_browse, container, false);
        initView(rootView);
        loading(0);
        return rootView;
    }

    public void initView(View v) {

        rvPostList = v.findViewById(R.id.rv_post_list);
        srlPostList = v.findViewById(R.id.srl_post_list);
        srlPostList.setColorSchemeColors(getResources().getColor(R.color.primary, null));
        rvPostList.setAdapter(mAdapter);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        rvPostList.setLayoutManager(layoutManager);

        srlPostList.setOnRefreshListener(() -> loading(MIN_REFRESHING_TIME));

        rvPostList.addOnScrollListener(new RecyclerAdapterLoadMoreWrapper.ReachBottomOnScrollListener() {
            @Override
            public void onLoadMore() {
                if (mAdapter.getLoadState() == RecyclerAdapterLoadMoreWrapper.LOADING)
                    return;
                mAdapter.setLoadState(RecyclerAdapterLoadMoreWrapper.LOADING);

                CompletableFuture.supplyAsync(() -> {
                    Log.d(LOG_TAG, "load 3");
                    long startTime = System.currentTimeMillis();
                    int refreshedCount = browseManager.load();
                    long waitingTime = startTime + MIN_LOADING_TIME - System.currentTimeMillis();
                    if (waitingTime > 0) {
                        try {
                            Thread.sleep(waitingTime);
                        } catch (InterruptedException ignored) { }
                    }
                    return refreshedCount;
                }).thenAccept((refreshedCount) -> requireActivity().runOnUiThread(() -> {
                    Log.d(LOG_TAG, "refresh: " + refreshedCount);
                    if (refreshedCount > 0)
                        mAdapter.setLoadState(RecyclerAdapterLoadMoreWrapper.LOADING_COMPLETE);
                    else
                        mAdapter.setLoadState(RecyclerAdapterLoadMoreWrapper.LOADING_END);
                }));
            }
        });
    }

    void loading(int minRefreshingTime) {
        long startTime = System.currentTimeMillis();
        // 这里分开写没有什么特殊的目的。早先版本的代码是前后端（Load 与 刷新界面）分离的，这里沿用传统。
        CompletableFuture.supplyAsync(() -> {
            browseManager.reset();
            Log.d(LOG_TAG, "load 2");
            return browseManager.load();

        }).thenAccept((result) -> {
            Log.d(LOG_TAG, "refresh list + ");
            long waitingTime = startTime + minRefreshingTime - System.currentTimeMillis();
            if (waitingTime > 0) {
                srlPostList.postDelayed(() -> {
                    if (srlPostList != null && srlPostList.isRefreshing()) {
                        srlPostList.setRefreshing(false);
                    }
                    mAdapter.setLoadState(RecyclerAdapterLoadMoreWrapper.LOADING_COMPLETE);
                }, waitingTime); // 延时一段时间，关闭下拉刷新
            } else {
                requireActivity().runOnUiThread(() -> {
                    if (srlPostList != null && srlPostList.isRefreshing()) {
                        srlPostList.setRefreshing(false);
                    }
                    mAdapter.setLoadState(RecyclerAdapterLoadMoreWrapper.LOADING_COMPLETE);
                });
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume");
    }

    @SuppressLint("NotifyDataSetChanged")
    public void reset() {
        mAdapter.notifyDataSetChanged();
        rvPostList.scrollToPosition(0);
    }
}